#pragma once

#include "register_value.h"
#include "memory.h"

template<size_t SIZE, typename register_t = typename register_value<SIZE>>
class sf_register {
	using value_t = typename register_t::value_t;
	using base_t = value_t*;

public:
	template <typename T>
	constexpr sf_register(T* base, size_t byte_offset = 0): _base{ reinterpret_cast<base_t>(reinterpret_cast<byte*>(base) + byte_offset) } {}

	constexpr size_t size() const& { return SIZE; }

private:
	base_t _base;

public:
	constexpr value_t read() const& {
		return *_base;
	}

	constexpr bit read(size_t pos) const& {
		return read() & (value_t(bit::T) << pos);
	}

	template <typename T>
	constexpr void write(T value) & {
		*_base = static_cast<value_t>(value);
	}

	constexpr void set(size_t pos) & {
		*_base |= value_t(bit::T) << pos;
	}

	constexpr void reset(size_t pos) & {
		*_base &= ~(value_t(bit::T) << pos);
	}

	constexpr base_t set_offset(size_t byte_offset) {
		return _base = reinterpret_cast<base_t>(reinterpret_cast<byte*>(_base) + byte_offset);
	}
};

